﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hiro.ActivationPoints;
using Hiro.ActivationPoints.Interfaces;
using Hiro.Loaders.Interfaces;
using LinFu.Reflection;

namespace Hiro.Loaders
{
    /// <summary>
    /// Represents a type that loads <see cref="ITypeActivationPoint"/> instances from the file system.
    /// </summary>
    public class ActivationPointLoader : IActivationPointLoader
    {
        private readonly IArgumentResolver _argumentResolver;
        private readonly IPropertyResolver _propertyResolver;
        private readonly IAssemblyLoader _assemblyLoader;

        /// <summary>
        /// Initializes a new instance of the ActivationPointLoader class.
        /// </summary>
        public ActivationPointLoader()
            : this(new ArgumentResolver())
        {
        }

        /// <summary>
        /// Initializes a new instance of the ActivationPointLoader class.
        /// </summary>
        /// <param name="argumentResolver">The resolver that will determine the dependencies that will be mapped to each constructor parameter.</param>
        public ActivationPointLoader(IArgumentResolver argumentResolver)
            : this(argumentResolver, new PropertyResolver())
        {
        }

        /// <summary>
        /// Initializes a new instance of the ActivationPointLoader class.
        /// </summary>
        /// <param name="argumentResolver">The resolver that will determine the dependencies that will be mapped to each constructor parameter.</param>
        /// <param name="propertyResolver">The resolver that will determine the dependencies that will be mapped to each property.</param>
        public ActivationPointLoader(IArgumentResolver argumentResolver, IPropertyResolver propertyResolver)
            : this(argumentResolver, propertyResolver, new AssemblyLoader())
        {
        }

        /// <summary>
        /// Initializes a new instance of the ActivationPointLoader class.
        /// </summary>
        /// <param name="argumentResolver">The resolver that will determine the dependencies that will be mapped to each constructor parameter.</param>
        /// <param name="propertyResolver">The resolver that will determine the dependencies that will be mapped to each property.</param>
        /// <param name="assemblyLoader">The assembly loader that will be used to read assemblies from the file system.</param>
        public ActivationPointLoader(IArgumentResolver argumentResolver, IPropertyResolver propertyResolver, IAssemblyLoader assemblyLoader)
        {
            _argumentResolver = argumentResolver;
            _propertyResolver = propertyResolver;
            _assemblyLoader = assemblyLoader;
        }

        /// <summary>
        /// Loads a set of activation points from a file system.
        /// </summary>
        /// <param name="directory">The target directory.</param>
        /// <param name="inputFiles">The wildcard pattern that denotes the files to be loaded.</param>
        /// <returns>A list of type activation points.</returns>
        public IList<ITypeActivationPoint> GetActivationPoints(string directory, string inputFiles)
        {
            // Load the list of type activation points
            var activationPoints = new List<ITypeActivationPoint>();
            var activationPointLoader = new
                CustomLoader<IList<ITypeActivationPoint>>(activationPoints, _assemblyLoader,
                new TypeActivationPointLoader(_argumentResolver, _propertyResolver));

            activationPointLoader.LoadFrom(directory,
                                           inputFiles);
            return activationPoints;
        }
    }
}
